<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Класс для чтения структуры таблиц базы данных
 * 
 * @package CoreFramework
 * @version 1.0
 * @author Gennadiy Kozlenko
 */
class Db_registry {
   
   /**
    * Instance
    *
    * @access private
    * @var object
    */
   var $_obj = null;
   
   /**
    * Массив структур таблиц
    *
    * @access private
    * @var array
    */
   var $_structuries = array();
   
   /**
    * Конструктор класса
    *
    * @access public
    * @return Db_registry
    */
   function Db_registry() {
      $this->_obj =& get_instance();
   } // end Db_registry
   
   /**
    * Получение структуры таблицы
    *
    * @access public
    * @param string $table
    * @return array
    */
   function get_structure($table) {
      if (!isset($this->_structures[$table])) {
         $this->_structures[$table] = $this->_load_structure($table);
      }
      return $this->_structures[$table];
   } // end get_structure
   
   /**
    * Загрузка структуры таблицы из базы
    *
    * @access public
    * @param string $table
    * @return array
    */
   function _load_structure($table) {
      $this->_obj->benchmark->mark('load_structure_(_' . $table . '_)_start');
      // Получаем инфу по полям
      $sql = "SHOW FIELDS FROM " . $this->_obj->db->dbprefix($table);
      $query = $this->_obj->db->query($sql);
      $fields = array();
      foreach ($query->result_array() as $value) {
         // Определяем тип и размер (если нужно)
         $type = 'unknown';
         $size = 0;
         $match = array();
         if (preg_match('~([a-z]+)(?:\((.*?)\))?~', $value['Type'], $match)) {
            switch (strtolower($match[1])) {
               // integer
               case 'int':
               case 'tinyint':
               case 'smallint':
               case 'mediumint':
               case 'integer':
               case 'bigint':
                  $type = 'integer';
                  break;
               // float
               case 'float':
               case 'double':
               case 'decimal':
                  $type = 'float';
                  break;
               // string
               case 'char':
               case 'varchar':
               case 'tinyblob':
               case 'blob':
               case 'mediumblob':
               case 'longblob':
               case 'tinytext':
               case 'text':
               case 'mediumtext':
               case 'longtext':
                  $type = 'string';
                  break;
               // enum
               case 'enum':
                  $type = 'enum';
                  break;
               // boolean
               case 'bit':
               case 'boolean':
                  $type = 'boolean';
                  break;
            }
            if (isset($match[2])) {
               switch ($type) {
                  case 'integer':
                     $size = 0;
                     break;
                  case 'enum':
                     $size = array();
                     foreach (explode(',', $match[2]) as $val) {
                        $val = trim($val, " '");
                        array_push($size, $val);
                     }
                     break;
                  default:
                     $size = $match[2];
               }
            }
         }
         $data = array(
            'default'        => $value['Default'],
            'not_null'       => 'NO' == $value['Null'] ? true : false,
            'auto_increment' => 'auto_increment' == $value['Extra'] ? true : false,
            'type'           => $type,
            'size'           => $size,
         );
         $fields[$value['Field']] = $data;
      }
      // Получаем инфу по индексам (primary and unique)
      $sql = "SHOW KEYS FROM " . $this->_obj->db->dbprefix($table);
      $query = $this->_obj->db->query($sql);
      $keys = array();
      foreach ($query->result_array() as $value) {
         if (!$value['Non_unique']) {
            $data = array(
               'fields' => array()
            );
            if (isset($keys[$value['Key_name']])) {
               $data = $keys[$value['Key_name']];
            }
            array_push($data['fields'], $value['Column_name']);
            $keys[$value['Key_name']] = $data;
         }
      }
      $structure = array(
         'fields' => $fields,
         'keys'   => $keys,
      );
      $this->_obj->benchmark->mark('load_structure_(_' . $table . '_)_end');
      return $structure;
   } // end _load_structure
   
}
